home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C++
/
Frameworks
/
Sprocket Framework DR2
/
Sprocket Framework
/
AEHandling.cp
< prev
next >
Wrap
Text File
|
1996-06-15
|
20KB
|
824 lines
/*
File: AppleEventHandling.cp
Project: Sprocket Framework 1.1 (DR2), released 6/15/96
Contains: Minimalist support for the required and Display Manager AppleEvents
We also support openning and printing “LetterSpec” documents for AOCE.
To Do: To really support AppleScript™, we’ll need to do ALOT more work in here.
Sprocket Major Contributors:
----------------------------
Dave Falkenburg, producer of Sprocket 1.0
Bill Hayden, producer of Sprocket 1.1
Steve Sisak, producer of the upcoming Sprocket 2.0
Pete Alexander Steve Falkenburg Randy Thelen
Eric Berdahl Nitin Ganatra Chris K. Thomas
Marshall Clow Dave Hershey Leonard Rosenthal
Tim Craycroft Dave Mark Dean Yu
David denBoer Gary Powell
Cameron Esfahani Jon Summers Apple Computer, Inc.
Comments, Additions, or Corrections:
------------------------------------
Bill Hayden, Nikol Software <nikol@codewell.com>
*/
#include "Sprocket.h"
#ifndef __APPLEEVENTS__
#include <AppleEvents.h>
#endif
#ifndef __AEREGISTRY__
#include <AERegistry.h>
#endif
#ifndef __DISPLAYS__
#include <Displays.h> // for Display Manager AppleEvent constants
#endif
#ifndef __PPCTOOLBOX__
#include <PPCToolbox.h>
#endif
#ifndef __EPPC__
#include <EPPC.h>
#endif
#if qInlineInputAware
#ifndef __TEXTSERVICES__
#include <TextServices.h>
#endif
#endif
#include "AEHandling.h"
static pascal Boolean StandardAEIdleProc(EventRecord *theEvent, long *sleepTime, RgnHandle *mouseRgn);
AEDesc gThisProcessDesc;
/*****************************************************************************/
void InitAppleEventRoutines(void)
{
ProcessSerialNumber thisProcess;
// Create useful AE Targets for our aplication
// By building the target in this fashion, we get the best performance
// out of the AppleEvent manager because it can call our event handlers
// inline.
thisProcess.highLongOfPSN = 0;
thisProcess.lowLongOfPSN = kCurrentProcess;
(void) AECreateDesc(typeProcessSerialNumber, (Ptr)&thisProcess, sizeof(ProcessSerialNumber), &gThisProcessDesc);
// It’s probably more efficient to use a table to install these handlers…
(void) AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, NewAEEventHandlerProc(HandleOpenApplication), 0, false);
(void) AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerProc(HandleOpenDocuments), 0, false);
(void) AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, NewAEEventHandlerProc(HandlePrintDocuments), 0, false);
(void) AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerProc(HandleQuitApplication), 0, false);
// regardless of whether or not we have the display manager, go ahead and register an AppleEvent handler
(void) AEInstallEventHandler(kCoreEventClass, kAESystemConfigNotice, NewAEEventHandlerProc(HandleSystemConfigNotice), 0, false);
// It’s probably more efficient to use a table to install these handlers…
(void) AEInstallEventHandler(kSprocketCommandClass, kProcessOneCommand, NewAEEventHandlerProc(HandleSprocketCommand), 0, false);
#if qInlineInputAware
if (gHasTextServices)
{
(void) AEInstallEventHandler(kTextServiceClass, kUpdateActiveInputArea, NewAEEventHandlerProc(HandleTextServicesUpdateActiveInputArea), 0, false);
(void) AEInstallEventHandler(kTextServiceClass, kPos2Offset, NewAEEventHandlerProc(HandleTextServicesPos2Offset), 0, false);
(void) AEInstallEventHandler(kTextServiceClass, kOffset2Pos, NewAEEventHandlerProc(HandleTextServicesOffset2Pos), 0, false);
// we don’t need to handle <kTextServiceClass, kShowHideInputWindow> events
}
#endif
}
/*****************************************************************************/
OSErr CheckAppleEventForMissingParams(AppleEvent *theAppleEvent)
{
DescType returnedType;
Size actualSize;
OSErr err;
err = AEGetAttributePtr(theAppleEvent,keyMissedKeywordAttr,typeWildCard,
&returnedType,nil,0,&actualSize);
if (err == errAEDescNotFound) // If we couldn’t find the error attribute
return noErr; // everything is ok, return noErr
if (err == noErr) // We found an error attribute, so
return errAEEventNotHandled; // tell the client we ignored the event
return err; // Something else happened, return it
}
/*****************************************************************************/
OSErr ChooseApplicationAsAETarget(AEAddressDesc *targetDesc, StringPtr prompt)
{
PortInfoRec thePortInfo;
LocationNameRec theLocation;
TargetID theTargetID;
OSErr err;
err = PPCBrowser(prompt, "\p", false, &theLocation, &thePortInfo, (PPCFilterUPP) NULL, "\p");
if (err == noErr)
{
theTargetID.name = thePortInfo.name;
theTargetID.location = theLocation;
err = AECreateDesc(typeTargetID, &theTargetID, sizeof(theTargetID), targetDesc);
}
return err;
}
/*****************************************************************************/
AEIdleUPP StandardAEIdleUPP = NewAEIdleProc(StandardAEIdleProc);
static pascal Boolean
StandardAEIdleProc(EventRecord *theEvent, long * /* sleepTime */, RgnHandle * /* mouseRgn */)
{
HandleEvent(theEvent); // First, always hand event off to our event handling code
return false;
}
/*****************************************************************************/
OSErr ForEachDocumentInList(AEDescList documentList,
EachDocumentProcPtr documentProc,
void * documentParam)
{
long documentCount,documentIndex;
DescType returnedType;
Size actualSize;
FSSpec theFSSpec;
AEKeyword keyword;
OSErr err;
if ((err = AECountItems(&documentList, &documentCount)) != noErr)
return err;
for (documentIndex=1; documentIndex <= documentCount; documentIndex++)
{
err = AEGetNthPtr(&documentList, documentIndex, typeFSS, &keyword, &returnedType,
(Ptr) &theFSSpec, sizeof(theFSSpec), &actualSize);
if (err == noErr)
(*documentProc)(&theFSSpec, documentParam);
else
break;
}
return err;
}
/*****************************************************************************/
#pragma mark ••• Required Events Support •••
pascal OSErr HandleOpenApplication(AppleEvent *theAppleEvent,AppleEvent * /*reply*/,long /*refCon*/)
{
OSErr err;
if ((err = CheckAppleEventForMissingParams(theAppleEvent)) != noErr)
return err;
return(CreateNewDocument());
}
/*****************************************************************************/
pascal OSErr HandleOpenDocuments(AppleEvent* theAppleEvent, AppleEvent* /*reply*/, long /*refCon*/)
{
AEDescList documentList;
OSErr err;
if ((err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &documentList)) != noErr)
return err;
if ((err = CheckAppleEventForMissingParams(theAppleEvent)) != noErr)
return err;
err = ForEachDocumentInList(documentList, &OpenDocument, nil);
(void) AEDisposeDesc(&documentList);
return err;
}
/*****************************************************************************/
pascal OSErr HandlePrintDocuments(AppleEvent *theAppleEvent, AppleEvent * /*reply*/, long /*refCon*/)
{
AEDescList documentList;
#if qUseQuickDrawGX
AEDescList desktopPrinterList;
FSSpec thePrinterFSSpec;
Boolean draggedToDesktopPrinter = false;
#endif
OSErr err;
if ((err = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&documentList)) != noErr)
return err;
#if qUseQuickDrawGX
if (noErr == AEGetAttributeDesc(theAppleEvent, keyOptionalKeywordAttr, typeAEList, &desktopPrinterList))
draggedToDesktopPrinter = true;
#endif
if ((err = CheckAppleEventForMissingParams(theAppleEvent)) != noErr)
return err;
#if qUseQuickDrawGX
if (draggedToDesktopPrinter)
{
DescType returnedType;
Size actualSize;
AEKeyword keyword;
err = AEGetNthPtr(&desktopPrinterList, 1, typeFSS, &keyword, &returnedType,
(Ptr) &thePrinterFSSpec, sizeof(thePrinterFSSpec), &actualSize);
(void) AEDisposeDesc(&desktopPrinterList);
}
err = ForEachDocumentInList(documentList, &PrintDocument, draggedToDesktopPrinter ? &thePrinterFSSpec : NULL);
(void) AEDisposeDesc(&documentList);
#else
err = ForEachDocumentInList(documentList, &PrintDocument, nil);
#endif
return err;
}
/*****************************************************************************/
pascal OSErr HandleQuitApplication(AppleEvent *theAppleEvent,AppleEvent * /* reply */,long /* refCon */)
{
OSErr err;
if ((err = CheckAppleEventForMissingParams(theAppleEvent)) != noErr)
return err;
gDone = QuitApplication();
if (gDone)
return noErr;
else
return userCanceledErr;
}
/*****************************************************************************/
#pragma mark ••• Sprocket Suite Support •••
OSErr SendCommandToSelf(CommandID theCommand)
{
OSErr err;
AEAddressDesc theTarget;
AppleEvent quitAE, replyAE;
ProcessSerialNumber psn;
if (!gHasAppleScript) // don't bother recording, just queue the command and return
{
err = QueueCommand(theCommand);
return err;
}
psn.highLongOfPSN = 0;
psn.lowLongOfPSN = kCurrentProcess;
err = AECreateDesc(typeProcessSerialNumber,
(Ptr)&psn,
sizeof(ProcessSerialNumber),
&theTarget);
if (err == noErr)
{
err = AECreateAppleEvent(kSprocketCommandClass, kProcessOneCommand, &theTarget,
kAutoGenerateReturnID, kAnyTransactionID, &quitAE);
if (err == noErr)
{
err = AEPutParamPtr( &quitAE, keyDirectObject, typeLongInteger,
(Ptr)(&theCommand), sizeof(CommandID) );
}
if (err == noErr)
{
err = AESend(&quitAE, &replyAE, kAENoReply + kAECanInteract,
kAENormalPriority, 3600, NULL, NULL);
}
err = AEDisposeDesc(&theTarget);
}
return err;
}
/*****************************************************************************/
pascal OSErr HandleSprocketCommand(AppleEvent* theAppleEvent, AppleEvent* /*reply*/, long /*refCon*/)
{
CommandID theCommand;
OSErr err;
long actualSize;
DescType actualType;
err = AEGetParamPtr(theAppleEvent, keyDirectObject, typeLongInteger, &actualType,
(UInt32 *)&theCommand, sizeof(UInt32), &actualSize);
if (err)
return err;
err = CheckAppleEventForMissingParams(theAppleEvent);
if (err)
return err;
err = QueueCommand(theCommand);
return err;
}
/*****************************************************************************/
#pragma mark ••• Display Manager Support •••
static OSErr HandleDeviceChange(DisplayIDType displayID, Rect *newRect);
static Boolean OutOfBoundsRect(GDHandle gd, WindowRef window, Rect screenRect);
static void MoveInbounds(WindowRef window, GDHandle gd, Rect screenRect);
static void ResizeInbounds(WindowRef window, GDHandle gd, Rect screenRect);
static GDHandle GetGreatestDevice(WindowRef window);
static void GetWindowRect(WindowRef window, Rect *windRect);
static void ResetStdState(WindowRef window);
#define kFudgeFactor 4 // fudge factor for boundary around window
#define kTitleBarHeight 18 // title bar height
pascal OSErr
HandleSystemConfigNotice(AppleEvent *event, AppleEvent * /* reply */,long /* refCon */)
{
OSErr err;
GrafPtr oldPort;
AEDescList displayList;
AEDescList aDisplay;
AERecord oldConfig,newConfig;
AEKeyword tempWord;
DisplayIDType displayID;
unsigned long returnType;
long count;
Rect oldRect, newRect;
GetPort(&oldPort);
// Get a list of the displays from the Display Notice AppleEvent.
err = AEGetParamDesc(event, kAEDisplayNotice, typeWildCard, &displayList);
// How many items in the list
err = AECountItems(&displayList,&count);
while (count > 0)
{ // Loop through the list.
err = AEGetNthDesc(&displayList, count, typeWildCard, &tempWord, &aDisplay);
// Get the Old Rect.
err = AEGetNthDesc(&aDisplay, 1, typeWildCard, &tempWord,
&oldConfig);
err = AEGetParamPtr(&oldConfig, keyDeviceRect, typeWildCard,
&returnType, &oldRect, 8, nil);
// Get the DisplayID so we can get the GDevice later.
err = AEGetParamPtr(&oldConfig, keyDisplayID, typeWildCard,
&returnType, &displayID, 8, nil);
// Get the New Rect.
err = AEGetNthDesc(&aDisplay, 2, typeWildCard, &tempWord, &newConfig);
err = AEGetParamPtr(&newConfig, keyDeviceRect, typeWildCard,
&returnType, &newRect, 8, nil);
// If the New and Old rects are not the same then we can assume
// the GDevice has changed and we need to rearrange the windows.
if (err == noErr && !EqualRect(&newRect, &oldRect))
HandleDeviceChange(displayID, &newRect);
count--;
err = AEDisposeDesc(&aDisplay);
err = AEDisposeDesc(&oldConfig);
err = AEDisposeDesc(&newConfig);
}
err = AEDisposeDesc(&displayList);
SetPort(oldPort);
return err;
}
/*****************************************************************************/
//----------------------------------------------------------------------
//
// HandleDeviceChange - called when the oldconfig is different from
// newconfig. Will check all windows on effected
// device and move if needed.
//----------------------------------------------------------------------
static OSErr HandleDeviceChange(DisplayIDType displayID, Rect *newRect)
{
OSErr err = noErr;
GDHandle gd;
GDHandle onGD;
WindowRef window;
Rect oldRect = *newRect; // save it for AdjustWindowSize
// Get the GDevice from the DisplayID.
err = DMGetGDeviceByDisplayID((DisplayIDType) displayID, &gd, false);
if (err == noErr && gd != nil)
{
window = FrontWindow();
while (window != nil)
{
SetPortWindowPort(window);
// which device holds the greatest portion of the window
onGD = GetGreatestDevice(window);
// If the window is not 50% or greater on
// the desired device then pass it up.
if (onGD == gd)
{
if (OutOfBoundsRect(gd, window, *newRect))
{
MoveInbounds(window, gd, *newRect);
if (OutOfBoundsRect(gd, window, *newRect))
{
ResizeInbounds(window, gd, *newRect);
// If it is one of our document windows then we need
// to reset the std state and the scroll bars.
TWindow* thisWindow = GetWindowObject(window);
if (thisWindow)
thisWindow->AdjustForNewWindowSize(&oldRect, newRect);
}
}
ResetStdState(window);
}
window = GetNextWindow(window);
}
}
return err;
}
/*****************************************************************************/
// Check to see if the window is out of the device rect.
static Boolean OutOfBoundsRect(GDHandle gd, WindowRef window, Rect screenRect)
{
Boolean out = false;
Rect windRect;
short mHeight = 0;
GetWindowRect(window, &windRect);
if (gd == GetMainDevice())
mHeight = GetMBarHeight();
if ((windRect.right > screenRect.right) || (windRect.bottom > screenRect.bottom))
out = true;
if ((windRect.left < screenRect.left) || (windRect.top < screenRect.top + mHeight))
out = true;
return out;
}
/*****************************************************************************/
// Move window onto the desired device
static void MoveInbounds(WindowRef window, GDHandle gd, Rect screenRect)
{
Rect bounds;
short mHeight = 0;
short hGlobal;
short vGlobal;
GetWindowRect(window, &bounds);
if (gd == GetMainDevice())
mHeight = GetMBarHeight();
hGlobal = bounds.left;
vGlobal = bounds.top + kTitleBarHeight;
// We want to make the left-top a priority so adjust it first
// as to override the bottom, right movements. This is so we
// can resize the window later.
if (((bounds.right - bounds.left) > (screenRect.right - screenRect.left)) ||
((bounds.bottom - bounds.top) >
((screenRect.bottom - screenRect.top) - mHeight)))
{
// adjust left
if (bounds.left < screenRect.left)
hGlobal = screenRect.left + kFudgeFactor;
// adjust top
if (bounds.top < screenRect.top + mHeight)
vGlobal = screenRect.top + kTitleBarHeight + mHeight + kFudgeFactor;
}
else
{
// adjust left
if (bounds.left < screenRect.left)
hGlobal = screenRect.left + kFudgeFactor;
else
{
// adjust right
if (bounds.right > screenRect.right)
hGlobal = (screenRect.right - (bounds.right - bounds.left)) - kFudgeFactor;
}
// adjust top
if (bounds.top < screenRect.top + mHeight)
vGlobal = screenRect.top + kTitleBarHeight + mHeight + kFudgeFactor;
else {
// adjust bottom
if (bounds.bottom > screenRect.bottom)
vGlobal = (screenRect.bottom - kFudgeFactor -
(bounds.bottom - bounds.top) + mHeight);
}
}
MoveWindow(window, hGlobal, vGlobal,false);
}
/*****************************************************************************/
// Resize the window to fit in the graphics device
static void ResizeInbounds(WindowRef window, GDHandle gd, Rect screenRect)
{
Rect windRect;
short h;
short v;
windRect = (GetWindowPort(window))->portRect;
// make the window bounds the size of the gdRect less the fudge factor.
h = windRect.right - windRect.left;
v = windRect.bottom - windRect.top;
if (h > screenRect.right - screenRect.left)
h = ((screenRect.right - screenRect.left) - (kFudgeFactor * 2));
if (v > screenRect.bottom - screenRect.top)
{
v = ((screenRect.bottom - screenRect.top) - (kFudgeFactor * 2));
// If we are on the main device then subtract the mBar
// height plus a fudge factor for a boundary.
if (gd == GetMainDevice())
v -= (GetMBarHeight() + kTitleBarHeight);
}
SizeWindow(window, h, v, true);
}
/*****************************************************************************/
// Find thw device that holds the greatest area of the window.
static GDHandle GetGreatestDevice(WindowRef window)
{
GDHandle gd;
GDHandle savedGD;
Rect gdRect;
Rect foundRect;
long size;
long greatest = nil;
gd = DMGetFirstScreenDevice(dmOnlyActiveDisplays);
savedGD = gd;
// Loop through the device list
while (gd != nil)
{
gdRect = (**gd).gdRect;
GlobalToLocal(&TopLeft(gdRect));
GlobalToLocal(&BotRight(gdRect));
if (SectRect(&(GetWindowPort(window))->portRect, &gdRect, &foundRect))
{
size = ((long)(foundRect.right - foundRect.left) *
(long)(foundRect.bottom - foundRect.top));
if (size > greatest)
{
greatest = size;
savedGD = gd; // save the greatest device
}
}
gd = DMGetNextScreenDevice(gd, dmOnlyActiveDisplays);
}
return savedGD;
}
/*****************************************************************************/
// Return the actual window rect in global coords
static void GetWindowRect(WindowRef window, Rect *windRect)
{
*windRect = (GetWindowPort(window))->portRect;
// add the titlebar height for actual height
windRect->top -= kTitleBarHeight;
LocalToGlobal(&TopLeft(*windRect));
LocalToGlobal(&BotRight(*windRect));
}
/*****************************************************************************/
// Since we are now on a different size screen we need
// to change the stdState window size so our zooming will work properly.
static void ResetStdState(WindowRef window)
{
Rect screenRect;
screenRect = (GetWindowPort(window))->portRect;
LocalToGlobal(&TopLeft(screenRect));
LocalToGlobal(&BotRight(screenRect));
SetWindowStandardState(window, &screenRect);
}
/*****************************************************************************/
#pragma mark ••• Inline Input Support •••
#if qInlineInputAware
pascal OSErr
HandleTextServicesUpdateActiveInputArea(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
{
DebugMessage("\pTextServicesUpdateActiveInputArea");
return errAEEventNotHandled; // we really don’t handle this yet...
}
/*****************************************************************************/
pascal OSErr
HandleTextServicesPos2Offset(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
{
DebugMessage("\pTextServicesPos2Offset");
return errAEEventNotHandled; // we really don’t handle this yet...
}
/*****************************************************************************/
pascal OSErr
HandleTextServicesOffset2Pos(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
{
DebugMessage("\pTextServicesOffset2Pos");
return errAEEventNotHandled; // we really don’t handle this yet...
}
#endif